/****************************************
* James Gomez                           *
* Project 3: Target Practice P3         *
* Comp 465                              *
* Professor Barnes                      *
* 12/7/2012                             *
*****************************************/

#ifndef _CHASE_CAMERA_
#define _CHASE_CAMERA_

#include "GomezJamesP3_OpenGL.h"
#include "GomezJamesP3_Camera.cpp"
#include "GomezJamesP3_Movable.cpp"

#include <string>
using namespace std;


/*************************************************************************
Camera class that will be anchored to a 3d object and hover at a distance 
away from that object. Chase cameras will be positioned behind its 3D
object anchor and oriented in the same manner as the 3D object. 
**************************************************************************/
class ChaseCamera: public Camera, public Movable{

private:
	Object3D * anchor;	

public:
	/*
	PARAMETERS
	name: name of this camera stored as a string
	anchor: pointer to a 3D object who's coordinates are to be used as an anchor
	offset: desired distance behind the anchor's local xy plane that the camera will be located
	hover: desired height above the anchor's local xz plane that the camera will hover
	elevation: desired angle rotation above the anchor's location. Can be used to set the lookat 
	slightly in front of or behind the 3D object.
	*/
	ChaseCamera(const string name, Object3D * anchor, const GLfloat offset,
		const GLfloat hoverAngle, const GLfloat lookUpAngle);
	~ChaseCamera(){}

	void setCameraView();
	void move();
};


ChaseCamera::ChaseCamera(const string name, Object3D * anchor, const GLfloat offset,
		const GLfloat hoverAngle, const GLfloat lookUpAngle): Camera(name){

	this->anchor = anchor;	
	
	//Store transformations specified by offset, hoverAngle, and lookUpAngle in OM.
	//This transformation will be applied to Anchor's TM and then saved as the Camera's 
	//TM every time move() is called.
	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	glLoadIdentity();
	glRotatef(hoverAngle, 1, 0, 0);
	glTranslatef(0, 0, -offset);
	glRotatef(lookUpAngle, -1, 0, 0);
	glGetFloatv(GL_MODELVIEW_MATRIX, OM);	

	//Apply transformation in OM to TM, then save as TM for this camera
	glLoadMatrixf(TM);
	glMultMatrixf(OM);
	glGetFloatv(GL_MODELVIEW_MATRIX, TM);	
	glPopMatrix();
}

void ChaseCamera::setCameraView(){
	GLfloat anchorTM[16]; 
	anchor->getTM(anchorTM);	

	//apply OM transformation to Anchor's TM and save as camera's TM
	glMatrixMode(GL_MODELVIEW);
	glLoadMatrixf(anchorTM);
	glMultMatrixf(OM);
	glGetFloatv(GL_MODELVIEW_MATRIX, TM);

	//convert TM from world to eye coordninates to set the camera's view
	GLfloat eyeM[16];
	worldToEyeCoordinates(TM, eyeM);
	glLoadMatrixf(eyeM);		
}

void ChaseCamera::move(){	
	setCameraView();
}

#endif